Skip to main content
  1. Writing/

Deleting All Workflow Runs In GitHub Repository With PowerShell

·618 words

Recently, I’ve been running a lot of GitHub Actions. Primarily because I automated some data collection for my Halo Infinite projects, and as part of that I get a lot of workflow logs. I mean, look at this massive list (you’ll be scrolling a bit):

Lots of GitHub Actions workflow runs. That means lots of log entries.
Lots of GitHub Actions workflow runs. That means lots of log entries.

As I was experimenting with the data aggregation tool, I also realized that maybe I want to also have a way to quickly delete those workflows so that they don’t pollute my Actions view.

Now, you might be wondering - won’t this be instantly addressed by the retention policy that you can set on GitHub? There is such a setting in your Settings > Actions > General section:

Artifact and log retention setting in GitHub.
Artifact and log retention setting in GitHub.

However, this setting doesn’t quite do what you think it does if you assumed that it will also clear out the workflow run entries. All it does is define the lifetime of logs within a specific workflow run, so that when you look at the logs for a step, it would end up looking like this:

Empty log inside a GitHub Actions run.
Empty log inside a GitHub Actions run.

Instead, what I wanted was removing the workflow entries themselves. As it turns out, there are two ways for me to do that - either using the GitHub API, or using the GitHub CLI to talk to the GitHub API. The latter seemed like a more fun option, so I put together this PowerShell script:

param (
    [string]$Owner,
    [string]$Repo
)

if (-not (Get-Command gh -ErrorAction SilentlyContinue)) {
    Write-Host "GitHub CLI (gh) is not installed. Please install it from https://cli.github.com/" -ForegroundColor Red
    exit 1
}

if (-not $Owner -or -not $Repo) {
    Write-Host "Usage: .\run.ps1 -Owner <GitHub-Owner> -Repo <GitHub-Repo>" -ForegroundColor Yellow
    exit 1
}

$workflowRuns = gh api repos/$Owner/$Repo/actions/runs --paginate --jq '.workflow_runs[].id'

foreach ($runId in $workflowRuns) {
    Write-Host "Deleting workflow run ID: $runId"
    gh api repos/$Owner/$Repo/actions/runs/$runId -X DELETE
}

Write-Host "All workflow runs have been deleted."

This script does a few things:

  1. Accepts the owner and the repository as arguments. You can run it as:

    .\run.ps1 -Owner <GitHub-Owner> -Repo <GitHub-Repo>`
    

    That way you’re not hard-coding any of the values within the script - it can run across other repositories at a moment’s notice.

  2. Checks if the GitHub CLI is installed by trying to call Get-Command on gh (which is how the GitHub CLI is invoked).

  3. Validates if both the owner and the repository name have been provided.

  4. Gets all of the workflow runs by calling the repos/$Owner/$Repo/actions/runs endpoint with --paginate (which ensures that additional HTTP requests are made to fetch all result pages) and storing their IDs.

  5. For each ID, call repos/$Owner/$Repo/actions/runs/$runId with a DELETE request to remove them.

Mole thinking.

Seems like you have to get every ID and then individually invoke the endpoint with a DELETE request. Is there a way to batch those up?

Great question with a somewhat unsatisfying answer - the GitHub API today doesn’t support batched deletion of workflow runs, so we kind of need to issue those request individually.

All this being said, though, let’s get to the meat and potatoes of this post. First, make sure you’re authenticated with your GitHub account:

gh auth login

Once you have your credentials stored, call the script with a repo to which you have access and where you want to erase all workflow runs. In my case, it was the repo I use with my machine account that is responsible for aggregating Halo Infinite wait times:

.\run.ps1 -Owner glibnub -Repo waittimes-aggregator
Running the script to delete the workflow runs in a GitHub repository.
Running the script to delete the workflow runs in a GitHub repository.

Nice! We now have an easy way to clean things up, even after a bunch of test runs.